package com.cn.lp.export.client.utils;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;

/**
 * 包含操作 {@code JSON} 数据的常用方法的工具类。
 *
 * @author KGTny
 * @version 1.0, 2009-6-27
 */
public final class JSONAide {

    private static final Object locker = new Object();

    private static volatile ObjectMapper mapper;

    private static Logger LOGGER = LoggerFactory.getLogger(JSONAide.class);

    private JSONAide() {

    }

    /**
     * 将对象转换成Json字符串
     *
     * @param obj
     * @return
     */
    public static String toJsonString(Object obj) {
        try {
            return getMapper().writeValueAsString(obj);
        } catch (JsonProcessingException ignored) {
            LOGGER.warn("json 编码失败 : ", ignored);
        }
        return "{}";
    }

    /**
     * 将Json字符串转换成对象
     *
     * @param jsonStr json字符串
     * @param clazz   转换目标类的Class
     * @return
     */
    public static <T> T toObject(String jsonStr, Class<T> clazz) {
        try {
            return getMapper().readValue(jsonStr, clazz);
        } catch (IOException ignored) {
            LOGGER.warn("json 解码失败 : ", ignored);
        }
        return null;
    }

    private static ObjectMapper getMapper() {
        if (mapper == null) {
            synchronized (locker) {
                if (mapper == null) {
                    mapper = new ObjectMapper();
                    mapper.setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE);
                    mapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);
                    mapper.setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);
                    mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
                    mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
                }
            }
        }
        return mapper;
    }

    public static void setMapper(ObjectMapper mapper) {
        JSONAide.mapper = mapper;
    }

    public static String toJson(Object value) {
        return toJson(getMapper(), value);
    }

    public static String toJson(ObjectMapper mapper, Object value) {
        try {
            return mapper.writeValueAsString(value);
        } catch (IOException e) {
            LOGGER.warn("json 编码失败 : ", e);
        }
        return "{}";
    }

    public static <T> T toObject(ObjectMapper mapper, String json, Class<T> clazz) {
        try {
            return mapper.readValue(json, clazz);
        } catch (IOException e) {
            LOGGER.warn("json 解码失败 : ", e);
        }
        return null;
    }

    public static <T> T toObject(String json, TypeReference<T> type) {
        return toObject(getMapper(), json, type);
    }

    public static <T> T toObject(ObjectMapper mapper, String json, TypeReference<T> type) {
        try {
            return mapper.readValue(json, type);
        } catch (IOException e) {
            LOGGER.warn("json 解码失败 : ", e);
        }
        return null;
    }

    public static <T> T toObject(InputStream inputStream, TypeReference<T> type) {
        return toObject(getMapper(), inputStream, type);
    }

    public static <T> T toObject(ObjectMapper mapper, InputStream inputStream, TypeReference<T> type) {
        try {
            return mapper.readValue(inputStream, type);
        } catch (IOException e) {
            LOGGER.warn("json 解码失败 : ", e);
        }
        return null;
    }

    public static <T> TypeReference<T> typeReference() {
        return new TypeReference<T>() {
        };
    }

    public static <T> TypeReference<T> tr() {
        return typeReference();
    }

}